package com.david.tvhelperapp.bluetooth

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothServerSocket
import android.bluetooth.BluetoothSocket
import android.os.Environment
import java.io.*
import java.util.*
import java.util.concurrent.Executors

/**
 * 通过蓝牙接收数据：指令数据／音频数据
 * TODO server端连接多个设备，接收多端指令；server端实现文件服务（提供上传文件，查看列表，下载，删除功能）
 * */
class BlueToothReceiver {
    val SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
    private val FILE_PATH = Environment.getExternalStorageDirectory().absolutePath + "/bluetooth/"

    private val TAG: String = BlueToothReceiver::class.java.getSimpleName()

    private val FLAG_MSG = 0 //消息标记

    private val FLAG_CENTENCE = 1 //语句标记
    private val FLAG_VOICE = 2 //音频流标记
    private val FLAG_FILE = 3 //文件标记

    private val VOICE_SEND_END:Byte = 10//语音发送完成

    private lateinit var mSSocket: BluetoothServerSocket


    private lateinit var mSocket: BluetoothSocket
    private var mOut: DataOutputStream? = null
    private var isRead = false
    private var isSending = false

    private var executorService = Executors.newFixedThreadPool(3)


    /**
     * 循环读取对方数据(若没有数据，则阻塞等待)
     */
    fun loopRead(socket: BluetoothSocket) {
        mSocket = socket
        try {
            if (!mSocket.isConnected()) mSocket.connect()
//                notifyUI(com.david.bluetooth.bt.BtBase.Listener.CONNECTED, mSocket.getRemoteDevice())
            mOut = DataOutputStream(mSocket.getOutputStream())
            val `in` = DataInputStream(mSocket.getInputStream())
            isRead = true
            while (isRead) { //死循环读取
                when (`in`.readInt()) {
                    FLAG_MSG -> {//读取数据{"action":"", "parameter":{}}
                        val msg = `in`.readUTF()
//                        notifyUI(com.david.bluetooth.bt.BtBase.Listener.MSG, "接收短消息：$msg")
                    }
                    FLAG_CENTENCE->{//接收语句，如：打开空调，打开灯
                        val centence = `in`.readUTF()
//                        notifyUI(com.david.bluetooth.bt.BtBase.Listener.MSG, "接收短消息：$msg")
                    }
                    FLAG_FILE -> {//接收文件
                        mkdirs(FILE_PATH)
                        val fileName = `in`.readUTF() //文件名
                        val fileLen = `in`.readLong() //文件长度
                        // 读取文件内容
                        var len: Long = 0
                        var r: Int
                        val b = ByteArray(4 * 1024)
                        val out =
                            FileOutputStream(FILE_PATH + fileName)
//                        notifyUI(
//                            com.david.bluetooth.bt.BtBase.Listener.MSG,
//                            "正在接收文件($fileName),请稍后..."
//                        )
                        while (`in`.read(b).also { r = it } != -1) {
                            out.write(b, 0, r)
                            len += r.toLong()
                            if (len >= fileLen) break
                        }
//                        notifyUI(
//                            com.david.bluetooth.bt.BtBase.Listener.MSG,
//                            "文件接收完成(存放在:" + com.david.bluetooth.bt.BtBase.FILE_PATH + ")"
//                        )
                    }
                    FLAG_VOICE -> {//接收到语音流后直接发送到nlp服务解析在发送到nlu服务理解


                        val b = ByteArray(4 * 1024)
                        val out = FileOutputStream("")//传给nlp服务的outPutStream
//                        notifyUI(
//                            com.david.bluetooth.bt.BtBase.Listener.MSG,
//                            "正在接收文件($fileName),请稍后..."
//                        )
                        var r: Int

                        while (`in`.read(b).also { r = it } != -1) {
                            out.write(b, 0, r)
                            //读取到只有一个字节且为VOICE_SEND_END时，结束接收，重新进入外循环
                            if (r == 1 &&  b[0] == VOICE_SEND_END)
                                break
                        }
                    }
                }
            }
        } catch (e: Throwable) {
            close()
        }
    }

    /**
     * 发送短消息
     */
    fun sendMsg(msg: String) {
        if (checkSend()) return
        isSending = true
        try {
            mOut!!.writeInt(FLAG_MSG) //消息标记
            mOut!!.writeUTF(msg)
            mOut!!.flush()
//            notifyUI(com.david.bluetooth.bt.BtBase.Listener.MSG, "发送短消息：$msg")
        } catch (e: Throwable) {
            close()
        }
        isSending = false
    }

    /**
     * 发送文件
     */
    fun sendFile(filePath: String) {
        if (checkSend()) return
        isSending = true
        executorService.execute(Runnable {
            try {
                val `in` = FileInputStream(filePath)
                val file = File(filePath)
                mOut!!.writeInt(FLAG_FILE) //文件标记
                mOut!!.writeUTF(file.name) //文件名
                mOut!!.writeLong(file.length()) //文件长度
                var r: Int
                val b = ByteArray(4 * 1024)
//                notifyUI(com.david.bluetooth.bt.BtBase.Listener.MSG, "正在发送文件($filePath),请稍后...")
                while (`in`.read(b).also { r = it } != -1) mOut!!.write(b, 0, r)
                mOut!!.flush()
//                notifyUI(com.david.bluetooth.bt.BtBase.Listener.MSG, "文件发送完成.")
            } catch (e: Throwable) {
                close()
            }
            isSending = false
        })
    }


    /**
     * 关闭Socket连接
     */
    fun close() {
        try {
            isRead = false
            mSocket.close()
//            notifyUI(com.david.bluetooth.bt.BtBase.Listener.DISCONNECTED, null)
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    /**
     * 断开连接并重新监听客户端发起的连接
     */
    fun listenConnect() {
        try {
            val adapter = BluetoothAdapter.getDefaultAdapter()
            //            mSSocket = adapter.listenUsingRfcommWithServiceRecord(TAG, SPP_UUID); //加密传输，Android强制执行配对，弹窗显示配对码
            mSSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(
                TAG,
                SPP_UUID
            ) //明文传输(不安全)，无需配对
            // 开启子线程
            executorService.execute(Runnable {
                try {
                    val socket: BluetoothSocket = mSSocket.accept() // 监听连接
                    mSSocket.close() // 关闭监听，只连接一个设备
                    loopRead(socket) // 循环读取
                } catch (e: Throwable) {
                    close()
                }
            })
        } catch (e: Throwable) {
            close()
        }
    }

    /**
     * 当前设备与指定设备是否连接
     */
    fun isConnected(dev: BluetoothDevice?): Boolean {
        val connected = mSocket != null && mSocket.isConnected
        return if (dev == null) connected else connected && mSocket.remoteDevice == dev
    }

    // ============================================通知UI===========================================================
    private fun checkSend(): Boolean {
        if (isSending) {
//            APP.toast("正在发送其它数据,请稍后再发...", 0)
            return true
        }
        return false
    }

    private fun mkdirs(filePath: String?) {
        if(filePath != null && !File(filePath).exists()) {
            val mk = File(filePath).mkdirs()
        }
    }
}